using System.Text;
using System.Text.Json;
using System.Threading;
using System.Collections.ObjectModel;
using KeyAuthService.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using WebSocketSharp;
using WebSocketSharp.Server;

namespace KeyAuthService.Services
{
    /// <summary>
    /// WebSocket服务器
    /// </summary>
    public class WebSocketServer
    {
        private readonly ILogger<WebSocketServer> _logger;
        private WebSocketSharp.Server.WebSocketServer _server;
        private readonly IServiceProvider _serviceProvider;
        private KeyAuthService? _keyAuthService;
        private readonly string _host = "127.0.0.1";
        private readonly int _port = 9876; // 修改为不常用端口
        private bool _isRunning = false;
        private int _connectedClients = 0; // 连接的客户端数量
        private readonly Dictionary<string, ConnectionInfo> _activeConnections = new Dictionary<string, ConnectionInfo>();

        public WebSocketServer(ILogger<WebSocketServer> logger, IServiceProvider serviceProvider)
        {
            _logger = logger;
            _serviceProvider = serviceProvider;
            // 创建新的WebSocketServer实例
            CreateNewServer();
        }

        /// <summary>
        /// 获取KeyAuthService实例（延迟初始化）
        /// </summary>
        private KeyAuthService KeyAuthService => _keyAuthService ??= _serviceProvider.GetRequiredService<KeyAuthService>();

        /// <summary>
        /// 创建新的WebSocketServer实例
        /// </summary>
        private void CreateNewServer()
        {
            _server = new WebSocketSharp.Server.WebSocketServer($"ws://{_host}:{_port}");
        }

        /// <summary>
        /// 启动服务器
        /// </summary>
        public bool Start()
        {
            if (_isRunning) return true;

            try
            {
                // 如果服务器曾经被停止过，重新创建实例
                if (_server == null)
                {
                    CreateNewServer();
                }

                // 添加服务处理器
                _server.AddWebSocketService<KeyAuthWebSocketHandler>("/", () => new KeyAuthWebSocketHandler(_logger, this, _serviceProvider));
                
                // 启动服务器
                _server.Start();
                _isRunning = true;
                _logger.LogInformation($"WebSocket服务器已启动，监听地址: ws://{_host}:{_port}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "启动WebSocket服务器失败");
                return false;
            }
        }

        /// <summary>
        /// 停止服务器
        /// </summary>
        public bool Stop()
        {
            if (!_isRunning) return true;

            try
            {
                _server.Stop();
                _isRunning = false;
                _connectedClients = 0; // 重置连接计数
                _activeConnections.Clear(); // 清除连接信息
                _logger.LogInformation("WebSocket服务器已停止");
                
                // 停止后重新创建服务器实例，解决"Already in use"问题
                CreateNewServer();
                
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "停止WebSocket服务器失败");
                return false;
            }
        }

        /// <summary>
        /// 是否正在运行
        /// </summary>
        public bool IsRunning => _isRunning;

        /// <summary>
        /// 获取当前连接的客户端数量
        /// </summary>
        public int ConnectedClients => _connectedClients;

        /// <summary>
        /// 获取所有活动连接信息
        /// </summary>
        public IReadOnlyCollection<ConnectionInfo> ActiveConnections => _activeConnections.Values.ToList().AsReadOnly();

        /// <summary>
        /// 增加连接计数并记录连接信息
        /// </summary>
        internal void AddConnection(string clientId, string remoteAddress)
        {
            Interlocked.Increment(ref _connectedClients);
            
            var connectionInfo = new ConnectionInfo
            {
                ClientId = clientId,
                ConnectedAt = DateTime.Now,
                RemoteAddress = remoteAddress,
                LastActivity = DateTime.Now
            };
            
            lock (_activeConnections)
            {
                _activeConnections[clientId] = connectionInfo;
            }
            
            _logger.LogInformation($"客户端连接，当前连接数: {_connectedClients}");
        }

        /// <summary>
        /// 减少连接计数并移除连接信息
        /// </summary>
        internal void RemoveConnection(string clientId)
        {
            Interlocked.Decrement(ref _connectedClients);
            
            lock (_activeConnections)
            {
                _activeConnections.Remove(clientId);
            }
            
            _logger.LogInformation($"客户端断开，当前连接数: {_connectedClients}");
        }

        /// <summary>
        /// 更新连接的最后活动时间
        /// </summary>
        internal void UpdateConnectionActivity(string clientId)
        {
            lock (_activeConnections)
            {
                if (_activeConnections.TryGetValue(clientId, out var connectionInfo))
                {
                    connectionInfo.LastActivity = DateTime.Now;
                }
            }
        }

        /// <summary>
        /// 更新连接的认证密钥信息
        /// </summary>
        internal void UpdateConnectionAuthKey(string clientId, string keyName)
        {
            lock (_activeConnections)
            {
                if (_activeConnections.TryGetValue(clientId, out var connectionInfo))
                {
                    connectionInfo.AuthKeyName = keyName;
                }
            }
        }

        /// <summary>
        /// 更新连接的密钥地址信息
        /// </summary>
        internal void UpdateConnectionKeyAddress(string clientId, string keyAddress)
        {
            lock (_activeConnections)
            {
                if (_activeConnections.TryGetValue(clientId, out var connectionInfo))
                {
                    connectionInfo.KeyAddress = keyAddress;
                }
            }
        }

        /// <summary>
        /// 获取连接使用的密钥名称
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        /// <returns>密钥名称，如果未找到则返回null</returns>
        public string? GetConnectionAuthKey(string clientId)
        {
            lock (_activeConnections)
            {
                if (_activeConnections.TryGetValue(clientId, out var connectionInfo))
                {
                    return connectionInfo.AuthKeyName;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取连接使用的密钥地址
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        /// <returns>密钥地址，如果未找到则返回null</returns>
        public string? GetConnectionKeyAddress(string clientId)
        {
            lock (_activeConnections)
            {
                if (_activeConnections.TryGetValue(clientId, out var connectionInfo))
                {
                    return connectionInfo.KeyAddress;
                }
            }
            return null;
        }
    }

    /// <summary>
    /// WebSocket处理器
    /// </summary>
    public class KeyAuthWebSocketHandler : WebSocketBehavior
    {
        private readonly ILogger _logger;
        private readonly WebSocketServer _webSocketServer;
        private readonly IServiceProvider _serviceProvider;
        private KeyAuthService? _keyAuthService;
        private string _clientId;
        private readonly DateTime _connectedAt;

        public KeyAuthWebSocketHandler(ILogger logger, WebSocketServer webSocketServer, IServiceProvider serviceProvider)
        {
            _logger = logger;
            _webSocketServer = webSocketServer;
            _serviceProvider = serviceProvider;
            _connectedAt = DateTime.Now;
        }

        /// <summary>
        /// 获取KeyAuthService实例（延迟初始化）
        /// </summary>
        private KeyAuthService KeyAuthService => _keyAuthService ??= _serviceProvider.GetRequiredService<KeyAuthService>();

        protected override void OnOpen()
        {
            _clientId = ID; // 使用WebSocketSharp提供的连接ID
            _webSocketServer.AddConnection(_clientId, Context.UserEndPoint.ToString());
            _logger.LogInformation($"客户端 {_clientId} 已连接");
        }

        protected override void OnClose(CloseEventArgs e)
        {
            // 清除连接的授权
            KeyAuthService.RemoveConnectionAuthorization(_clientId);

            // 移除连接信息
            _webSocketServer.RemoveConnection(_clientId);
            _logger.LogInformation($"客户端 {_clientId} 已断开连接，代码: {e.Code}，原因: {e.Reason}");
        }

        protected override void OnError(ErrorEventArgs e)
        {
            _logger.LogError(e.Exception, $"客户端 {_clientId} 发生错误");
        }

        protected override void OnMessage(MessageEventArgs e)
        {
            if (e.IsText)
            {
                try
                {
                    _webSocketServer.UpdateConnectionActivity(_clientId);
                    
                    // 解析请求
                    var request = JsonSerializer.Deserialize<WebSocketRequest>(e.Data);
                    if (request == null)
                    {
                        SendErrorResponse("invalid_request", "无效的请求格式", string.Empty);
                        return;
                    }

                    // 设置客户端ID
                    request.ClientId = _clientId;

                    _logger.LogInformation($"收到客户端 {_clientId} 的请求: {request.Action}");

                    // 处理请求
                    var response = KeyAuthService.HandleRequest(request);

                    // 发送响应
                    string responseJson = JsonSerializer.Serialize(response);
                    Send(responseJson);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"处理客户端 {_clientId} 的消息时发生异常");
                    SendErrorResponse("internal_error", "内部服务器错误", string.Empty);
                }
            }
            else
            {
                _logger.LogWarning($"收到客户端 {_clientId} 的非文本消息，已忽略");
            }
        }

        /// <summary>
        /// 发送错误响应
        /// </summary>
        private void SendErrorResponse(string code, string message, string requestId)
        {
            var response = WebSocketResponse.CreateError(requestId, code, message);
            string responseJson = JsonSerializer.Serialize(response);
            Send(responseJson);
        }
    }
} 